package com.dwxt.parabolic.service;

import com.dwxt.common.base.BaseResult;
import com.dwxt.common.base.Page;
import com.dwxt.common.base.StatusCode;
import com.dwxt.common.base.YesOrNo;
import com.dwxt.common.util.IDUtils;
import com.dwxt.common.util.JsonUtils;
import com.dwxt.common.util.OkHttpUtils;
import com.dwxt.parabolic.base.EventCode;
import com.dwxt.parabolic.base.QuantityType;
import com.dwxt.parabolic.dao.DeviceMapper;
import com.dwxt.parabolic.entity.*;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.commons.util.IdUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class DeviceService {
    @Autowired
    private DeviceMapper deviceMapper;

    @Autowired
    private CompanyService companyService;

    @Autowired
    private CameraService cameraService;

    @Autowired
    private EventService eventService;

    public BaseResult getDeviceList(Page page, Device device) {
        PageHelper.startPage(page.getPageNum(), page.getPageSize());
        DeviceExample example = new DeviceExample();
        example.setOrderByClause("create_time desc");
        DeviceExample.Criteria criteria = example.createCriteria();
        if (StringUtils.isNotBlank(device.getCompanyId())) {
            criteria.andCompanyIdEqualTo(device.getCompanyId());
        }
        if (StringUtils.isNotBlank(device.getName())) {
            criteria.andNameLike("%" + device.getName() + "%");
        }
        if (StringUtils.isNotBlank(device.getSerial())) {
            criteria.andSerialLike("%" + device.getSerial() + "%");
        }
        if (Optional.ofNullable(device).map(Device::getStatus).isPresent()) {
            criteria.andStatusEqualTo(device.getStatus());
        }
        List<Device> deviceList = deviceMapper.selectByExample(example);
        PageInfo pageInfo = new PageInfo(deviceList);
        return BaseResult.ok(pageInfo);
    }

    @Transactional
    public BaseResult add(Device device) {
        device.setId(IDUtils.genItemId());
        Device selectBySerial = selectBySerial(device.getSerial());
        if (selectBySerial != null) {
            return BaseResult.build(StatusCode.SERIAL_EXIST);
        }
        deviceMapper.insertSelective(device);
        //更改公司超脑数量,数量+1
        companyService.addByQuantityType(device.getCompanyId(), QuantityType.device, 1);
        return BaseResult.ok();
    }

    public Device selectBySerial(String serial) {
        DeviceExample example = new DeviceExample();
        example.createCriteria().andSerialEqualTo(serial);
        List<Device> deviceList = deviceMapper.selectByExample(example);
        return deviceList.size() > 0 ? deviceList.get(0) : null;
    }

    public BaseResult update(Device device) {
        if (Optional.ofNullable(device).map(Device::getSerial).map(this::selectBySerial).filter(device1 -> !device1.getId().equals(device.getId())).isPresent()) {
            return BaseResult.build(StatusCode.SERIAL_EXIST);
        }
        deviceMapper.updateByPrimaryKeySelective(device);
        return BaseResult.ok();
    }

    @Transactional
    public BaseResult delete(String id) {
        Device device = deviceMapper.selectByPrimaryKey(id);
        deviceMapper.deleteByPrimaryKey(id);
        companyService.addByQuantityType(device.getCompanyId(), QuantityType.device, -1);
        return BaseResult.ok();
    }

    @Transactional
    public BaseResult check(String id) {
        Device device = deviceMapper.selectByPrimaryKey(id);
        String url = "http://" + device.getIp();
        String res = OkHttpUtils.synGet(url, null);
        if (StringUtils.isNotBlank(res)) {
            device.setIsOnline(YesOrNo.YES);
            deviceMapper.updateByPrimaryKeySelective(device);
            return BaseResult.ok();
            //return BaseResult.ok();
        } else {
            eventService.insertEvent(device);
            device.setIsOnline(YesOrNo.NO);
            deviceMapper.updateByPrimaryKeySelective(device);
            return BaseResult.build(StatusCode.DEVICE_CHECK_FAIL);
        }

    }

    public BaseResult getAllDeviceOfCompany(String companyId) {
        List<Device> companyList = selectByCompanyId(companyId);
        return BaseResult.ok(companyList);
    }

    public List<Device> selectByCompanyId(String companyId) {
        DeviceExample example = new DeviceExample();
        example.createCriteria().andCompanyIdEqualTo(companyId);
        return deviceMapper.selectByExample(example);
    }

    public BaseResult startOrEnd(String id) {
        //查询启动状态的相机
        List<Camera> cameraList = cameraService.selectAllStartCameraOfDevice(id);
        if (cameraList.size() == 0) {
            return BaseResult.build(StatusCode.CAMERA_NOT_EXIST);
        }
        Device device = deviceMapper.selectByPrimaryKey(id);
        //调用超脑接口，启动算法
        String url = "http://" + device.getIp() + "/algorithm";
        Map para = new HashMap();
        para.put("cameraList", cameraList);
        Integer status = device.getStatus();
        para.put("action", status == YesOrNo.YES ? "end" : "start");
        String res = OkHttpUtils.jsonPost(url, JsonUtils.objectToJson(para), null);
        //System.out.println(res);
        if (res == null || res.equalsIgnoreCase("Internal Server Error") || !(JSONObject.fromObject(res).getInt("status") == 200)) {
            return BaseResult.build(StatusCode.DEVICE_FAIL);
        }
        //修改设备状态
        device.setStatus(status == YesOrNo.YES ? YesOrNo.NO : YesOrNo.YES);
        deviceMapper.updateByPrimaryKeySelective(device);

        //开启或关闭相机
        cameraService.startOrEndByDeviceId(id, status == YesOrNo.YES ? YesOrNo.NO : YesOrNo.YES);
        return BaseResult.ok();
    }

    public Device selectByPrimaryKey(String deviceId) {
        return deviceMapper.selectByPrimaryKey(deviceId);
    }

    public void updateByPrimaryKeySelective(Device device) {
        deviceMapper.updateByPrimaryKeySelective(device);
    }

    public List<Device> selectByCompanyIdList(List<String> collect) {
        DeviceExample example = new DeviceExample();
        example.createCriteria().andCompanyIdIn(collect);
        return deviceMapper.selectByExample(example);
    }

    public void endAllByInstallId(String id) {
        List<Company> companyList =
                companyService.selectByInstallCompanyId(id).stream().filter(company -> company.getStatus() == YesOrNo.YES).collect(Collectors.toList());
        for (Company company : companyList) {
            endByCompanyId(company.getId());
            company.setStatus(YesOrNo.NO);
            companyService.updateByPrimaryKeySelective(company);
        }
    }

    public void endByCompanyId(String companyId) {
        List<Device> deviceList =
                selectByCompanyId(companyId).stream().filter(device -> device.getStatus() == YesOrNo.YES).collect(Collectors.toList());
        for (Device device : deviceList) {
            endByDevice(device);
            device.setStatus(YesOrNo.NO);
            updateByPrimaryKeySelective(device);
        }
    }

    private void endByDevice(Device device) {
        //查询启动状态的相机
        List<Camera> cameraList = cameraService.selectAllStartCameraOfDevice(device.getId());
        if (cameraList.size() == 0) {
            return;
        }
        //调用超脑接口，启动算法
        String url = "http://" + device.getIp() + "/algorithm";
        Map para = new HashMap();
        para.put("cameraList", cameraList);
        para.put("action", "end");
        String res = OkHttpUtils.jsonPost(url, JsonUtils.objectToJson(para), null);
        //System.out.println(res);
        //关闭相机
        cameraService.startOrEndByDeviceId(device.getId(), YesOrNo.NO);
        return;
    }
}
